﻿namespace EveKillboard.Core.Services
{
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Net;
    using System.Xml.XPath;
    using Interfaces;
    
    public sealed class EvePriceServicesProvider : IItemPriceService, ITraceSource
    {
        const string EVE_CENTRAL = "http://api.eve-central.com/api/marketstat?typeid={0}";
        const string EC_XPATH = "/evec_api/marketstat/type/all/median";
        
       
        public EvePriceServicesProvider(TraceSource traceSource = null)
        {
            Trace = traceSource ?? new TraceSource("EvePriceServicesProvider");
        }

        public TraceSource Trace { get; set; }

        public decimal? GetPrice(int itemId)
        {
            this.TraceEvent(TraceEventType.Information,"Requesting item \"{0}\" current price.", itemId);

            return GetPriceFrom(string.Format(EVE_CENTRAL, itemId), EC_XPATH);
        }

        decimal? GetPriceFrom(string url, string xpath)
        {
            this.TraceEvent(TraceEventType.Information, "Requesting price from uri:{0}", url);

            decimal? price = null;
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(url);
                request.Timeout = 5000;
                request.KeepAlive = false;
                
                var response = request.GetResponse();
                var st = response.GetResponseStream();
                if(st!=null)
                    using (st)
                    {
                        var node = new XPathDocument(st)
                            .CreateNavigator()
                            .SelectSingleNode(xpath);

                        price = node == null || string.IsNullOrEmpty(node.Value) || string.Equals("null", node.Value)
                            ? (decimal?)null
                            : Math.Round(decimal.Parse(node.Value, CultureInfo.InvariantCulture), 2);
                    }

                response.Close();
            }
            catch (Exception exp)
            {
                this.TraceEvent(TraceEventType.Error, "The request to \"{0}\" has thrown an exception of type \"{1}\". Details: {2}", url, exp.GetType(), exp.Message);
            }

            return price;
        }
    }
}